package com.genersoft.iot.vmp.service.impl;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.core.rolling.RollingFileAppender;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.service.ILogService;
import com.genersoft.iot.vmp.service.bean.LogFileInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.*;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class LogServiceImpl implements ILogService {

    @Override
    public List<LogFileInfo> queryList(String query, String startTime, String endTime) {
        File logFile = getLogDir();
        if (logFile == null || !logFile.exists()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取日志文件目录失败");
        }
        File[] files = logFile.listFiles();
        //如果将文件名的前缀为sip,则跳过，否则将文件名的前缀改名为SkyPatrol，
        if (files != null) {
            for (File file : files) {
                // 打印当前操作的文件
                log.info("当前操作的文件为: {}", file);
                // 获取当前文件名的前缀
                String current = file.getName().substring(0, file.getName().indexOf('-'));
                log.info("当前文件名的前缀为: {}", current);

                // 如果文件名的前缀为 "sip" 或 "SkyPatrol"，则跳过
                if (current.equals("sip") || current.equals("SkyPatrol")) {
                    log.info("跳过文件: {}", file.getName());
                    continue;
                }

                // 否则将文件名的前缀改名为 "SkyPatrol"
                String newFileName = "SkyPatrol" + file.getName().substring(file.getName().indexOf("-"));
                File newFile = new File(file.getParent(), newFileName);

                // 检查目标文件是否已存在
                if (newFile.exists()) {
                    log.error("目标文件已存在: {}", newFile.getName());
                    continue;
                }

                // 重命名文件
                if (file.renameTo(newFile)) {
                    log.info("文件重命名为: {}", newFile.getName());
                } else {
                    // 如果重命名失败，尝试使用 Files.move 方法
                    try {
                        Path sourcePath = Paths.get(file.getAbsolutePath());
                        Path targetPath = Paths.get(newFile.getAbsolutePath());
                        Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
                        log.info("文件重命名为: {}", newFile.getName());
                    } catch (IOException e) {
                        log.error("文件重命名失败: {}", file.getName(), e);
                    }
                }
            }
        }
        log.info("获取的文件列表为"+ Arrays.toString(files));
        List<LogFileInfo> result = new ArrayList<>();
        if (files == null || files.length == 0) {
            return result;
        }

        // 读取文件创建时间作为开始时间，修改时间为结束时间
        Long startTimestamp = null;
        if (startTime != null) {
            startTimestamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(startTime);
        }
        Long endTimestamp = null;
        if (endTime != null) {
            endTimestamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(endTime);
        }
        for (File file : files) {
            LogFileInfo logFileInfo = new LogFileInfo();//创建文件信息对象
            logFileInfo.setFileName(file.getName());//获取文件名
            logFileInfo.setFileSize(file.length());//获取文件的大小
            if (query != null && !file.getName().contains(query)) {
                continue;
            }
            try {
                Long[] fileAttributes = getFileAttributes(file);

                if (fileAttributes == null) {
                    continue;
                }
                long startTimestampForFile = fileAttributes[0];
                long endTimestampForFile = fileAttributes[1];
                logFileInfo.setStartTime(startTimestampForFile);
                logFileInfo.setEndTime(endTimestampForFile);
                if (startTimestamp != null && startTimestamp > startTimestampForFile) {
                    continue;
                }
                if (endTimestamp != null && endTimestamp < endTimestampForFile) {
                    continue;
                }
            } catch (IOException e) {
                log.error("[读取日志文件列表] 获取创建时间和修改时间失败", e);
                continue;
            }
            result.add(logFileInfo);

        }
        result.sort((o1, o2) -> o2.getStartTime().compareTo(o1.getStartTime()));
        return result;
    }

    private File getLogDir() {
        Logger logger = (Logger) LoggerFactory.getLogger("root");
        RollingFileAppender rollingFileAppender = (RollingFileAppender) logger.getAppender("RollingFile");
        File rollingFile = new File(rollingFileAppender.getFile());
        return rollingFile.getParentFile();
    }

    Long[] getFileAttributes(File file) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        String startLine = bufferedReader.readLine();
        if (startLine== null) {
            return null;
        }
        String startTime = startLine.substring(0, 19);

        // 最后一行的开头不一定是时间
//        String lastLine = "";
//        try (ReversedLinesFileReader reversedLinesReader = new ReversedLinesFileReader(file, Charset.defaultCharset())) {
//            lastLine = reversedLinesReader.readLine();
//        } catch (Exception e) {
//            log.error("file read error, msg:{}", e.getMessage(), e);
//        }
//        String endTime = lastLine.substring(0, 19);
        return new Long[]{DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(startTime), file.lastModified()};
    }

    @Override
    public File getFileByName(String fileName) {
        File logDir = getLogDir();
        return new File(logDir, fileName);
    }
    public boolean deleteFileByName(String fileName) {
        File logDir = getLogDir();
        if (logDir == null || !logDir.exists() || !logDir.isDirectory()) {
            log.error("❌ 目录无效 - 路径: {}", logDir);
            return false;
        }

        File targetFile = new File(logDir, fileName);
        log.info("🔍 尝试删除文件 - 绝对路径: {}", targetFile.getAbsolutePath());

        // 增强文件状态检查
        log.info("📋 文件状态 - 存在: {}, 是文件: {}, 大小: {}字节",
                targetFile.exists(),
                targetFile.isFile(),
                targetFile.length());

        // 权限检查（重点）
        log.info("🔐 权限检查 - 可读: {}, 可写: {}, 可执行: {}",
                targetFile.canRead(),
                targetFile.canWrite(),
                targetFile.canExecute());

        if (targetFile.exists() && targetFile.isFile()) {
            // 添加删除重试机制
            int retryCount = 3;
            while (retryCount-- > 0) {
                if (targetFile.delete()) {
                    log.info("✅ 删除成功 - 文件: {}", fileName);
                    return true;
                } else {
                    log.warn("⚠️ 删除失败 (剩余重试 {} 次) - 可能原因: {}",
                            retryCount, getDeleteFailureReason(targetFile));
                    try {
                        Thread.sleep(500); // 等待500ms后重试
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
            //如果上面的方式无法删除，那么再尝试下面的方式通过NIO强制删除成功
            try {
                Files.delete(targetFile.toPath());
                log.info("🛠️ 通过NIO强制删除成功");
                return true;
            } catch (IOException e) {
                log.error("💥 最终删除失败", e);
                // 打印操作系统级错误信息
                if (e instanceof AccessDeniedException) {
                    try {
                        log.error("🔒 权限不足 - 运行用户: {}, 文件所有者: {}",
                                System.getProperty("user.name"),
                                Files.getOwner(targetFile.toPath()));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            }
        }
        return false;
    }

    // 获取删除失败的具体原因
    private String getDeleteFailureReason(File file) {
        try {
            if (!file.canWrite()) return "文件不可写";
            if (Files.isSymbolicLink(file.toPath())) return "符号链接文件";
            if (!file.getAbsolutePath().equals(file.getCanonicalPath())) return "路径解析不一致";
            return "未知原因（可能被其他进程锁定）";
        } catch (IOException e) {
            return "IO异常: " + e.getMessage();
        }
    }
}
